{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/Qiskit/qiskit-tutorials/master/images/qiskit-heading.png\" alt=\"Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook\" width=\"500 px\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  _*Let's play a quantum game!*_\n",
    "\n",
    "Quantum games are similar to probability games played in a casino. They usually involve several players who cooperatively play a game against the house (sometimes called referee). The players are given some random inputs, and they have to make a choice on which output to give back to the house. They are not allowed to communicate during the game, so they have to prepare a strategy in advance in order to have the best chance to win the game.\n",
    "To win the game, the outputs given by the players have to satisfy a certain condition characteristic of the game played.\n",
    "\n",
    "For such games, the players are allowed to use either classical or quantum strategies. We'll see in more details what is meant by classical/quantum strategy once we go into the game. For now, just think of it as the kinds of manipulations they are allowed to do. In classical strategies, they are only allowed to manipulate their inputs classically, that is with the help of objects whose behaviour can be described using classical physics. In quantum strategies, they are allowed to use quantum objects (which follow the rules of quantum mechanics) to manipulate the inputs given to them.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Contributors\n",
    "Mirko Amico\n",
    "\n",
    "### Qiskit Package Versions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'qiskit': '0.10.3',\n",
       " 'qiskit-terra': '0.8.1',\n",
       " 'qiskit-ignis': '0.1.1',\n",
       " 'qiskit-aer': '0.2.1',\n",
       " 'qiskit-ibmq-provider': '0.2.2',\n",
       " 'qiskit-aqua': '0.5.1'}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "qiskit.__qiskit_version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Quantum computation\n",
    "\n",
    "Quantum computation is a new kind of computation which differs from the current way of doing computations in the same way quantum strategies differ from classical strategies.\n",
    "Classical computations can be implemented in several ways, the most successful one today is the circuit model of computation. This is how elements in modern computers are designed. In the circuit model, a computation is made by taking a string of bits as inputs, doing certain operations on them and giving a new string of bits as output. In the current paradigm, these operation are logical operations that follow Boole's logic. It was proved that one needs to be able to carry out a limited set of operation (namely \"not gate\", and \"and gate\") in order to implement any operation (addition, multiplication, division, ... ) by a combination of operation from this set. This fundamental set of gates is called an \"elementary set of gates\" and is all that is required to be able to do any computation.\n",
    "Similarly to classical computation, quantum computation can be done using the circuit model of computation. In this case, bits are replaced by qubits and logic gates must be substituted with quantum gates which can operate on qubits while keeping intact their special quantum properties.\n",
    "Here there is another difference which we haven't mentioned, quantum circuits must be reversible due to the reversibility ineherent in the laws of quantum mechanics. A reversible circuit allows you to run the computation backwards and retrieve the inputs given the outputs. Classical computation can also be imnplemented using reversible gates but there are disadvanteges with regards to the circuit size and complexity. Thus modern computer are built with \"irreversible\" logic (which means it's impossible to run the computation backwards, see truth table of the \"AND\" gate for example) and this is the reason why the generate heat! In order to have reversible quantum gates, one must implement these gates using, what is called \"unitary operations\", that is operations which preserve the sum of the probabilities of seeing each of the measurable values of the qubits. Altough, the probability of seeing any single outcome can change, their sum will always add up to one. \n",
    "\n",
    "## Qubits\n",
    "\n",
    "In quantum computation the objects of the computation are quantum objects called qubits. Similarly to bits, qubits can take two values: \n",
    "$$\\lvert 0 \\rangle , \\lvert 1 \\rangle .$$\n",
    "\n",
    "Where the brackets around the number points to the fact that these are quantum objects (see Dirac's notation).\n",
    "Differently from the regular bits stored in a computer, which can either take the value of \"0\" or \"1\", qubits can be in a superposition of \"0\" and \"1\".\n",
    "$$\\alpha \\lvert 0 \\rangle + \\beta \\lvert 1 \\rangle,$$\n",
    "\n",
    "where $\\alpha$ and $\\beta$ are complex numbers and are related to the probability of obtaining the corresponding outcome $\\lvert 0 \\rangle$ or $\\lvert 1 \\rangle$.\n",
    "\n",
    "$$P(qubit \\, state = 0) = \\lvert \\alpha \\rvert^{2}$$\n",
    "$$P(qubit \\, state = 1) = \\lvert \\beta \\rvert^{2}$$\n",
    "\n",
    "\n",
    "Which means the qubit has simultaneously the value \"0\" and \"1\" and, only when measured, will take one of the two values with probability $\\lvert \\alpha \\rvert^{2}$ and $\\lvert \\beta \\rvert^{2}$ respectively.\n",
    "Another interesting property of qubits, which departs from the classical world, is that they can be entangled. If qubits are entangled with each other, the value taken by each of them is strictly related to the value taken by the other. The correlations between the values of entangled qubits is so strong that it cannot be described by classical probability theory. This is one of the most peculiar features of quantum mechanics. In a way, entangled qubits lose their identity as individual objects, as their properties now depend on the properties of the other objects with which they are entangled. It's not possible to separate an entangled system in independent parts and it must be treated as a new unit (in quantum mechanical terms, the state of the whole system is not separable. it cannot be factorized as product state of the state of individual systems).\n",
    "However, in order to know about these quantum objects we must make a measurement of their state. This, causes the system to take one particular value among a set that are compatible to its state. It is not possible to determine with certainity which value the system will take, but one can only know the various probabilities for the allowed values and then sit back and watch what the system \"chooses\".\n",
    "\n",
    "## Quantum gates\n",
    "\n",
    "Quantum gates implement operations on qubit by keeping intact their quantum properties. Furthermore, they allow some of those properties to arise, for example by putting qubits in a superposition of states or entangling with each other.\n",
    "Let's see some quantum gates:\n",
    "\n",
    "### One-qubit gates\n",
    "These gates act on a qubit, affecting its state:\n",
    "\n",
    "<b>X</b>: flips the state of a qubit from $\\lvert 0 \\rangle \\rightarrow \\lvert 1 \\rangle $ and $\\lvert 1 \\rangle \\rightarrow \\lvert 0 \\rangle $  .\n",
    "\n",
    "<b>Z</b>: flips the phase of a qubit (changes relative sign of $\\alpha$ and $\\beta$).\n",
    "\n",
    "<b>Y</b>: flips the state of a qubit and its phase.\n",
    "\n",
    "<b>H</b>: puts qubit in a superposition of $\\lvert 0 \\rangle$  and $\\lvert 1 \\rangle$\n",
    "\n",
    "<b>Rotations around an axis ($R_x, R_y, R_z$)</b>: Rotates qubit, by changing the coefficients $\\alpha, \\beta$ in a way that depends on the angle of rotation.\n",
    "\n",
    "\n",
    "### Two-qubit gates\n",
    "The most important two qubit gate is the controlled-not gate:\n",
    "\n",
    "<b>CX</b>: flips the state of a qubit conditionally on the state of another qubit.\n",
    "\n",
    "In more details, one of the qubit is taken as control qubit (and it is unaffected by the gate) and the other as target qubit. If the control qubit is in the state $\\lvert 0 \\rangle$, nothing is done to the target qubit. If the control qubit is in state $\\lvert 1 \\rangle$, the <b>X</b> gate (bit-flip) is apllied to the target qubit.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Writing a quantum algorithm for a quantum game\n",
    "\n",
    "Ok, enough with the theory! Let's get our hands dirty and write a simple quantum game which will bring the quantum weirdness all the way from the textbooks to your personal computer!\n",
    "\n",
    "In this tutorial we will see what has been called the CHSH (John Clauser, Michael Horne, Abner Shimony, and Richard Holt) game. Although related to the CHSH inequality [3], it doesn't really share the same authors and its origin appear to be lost in the history of quantum computation.\n",
    "\n",
    "The game involves two players (Alice and Bob) who play against the house. Alice and Bob can discuss and pick a strategy before the game starts, but are not allowed to communicate after the beginning of the game. A referee generates two random bits <b>x</b> and <b>y</b> which are then given as inputs to Alice and Bob respectively. Alice and Bob do not know each other's inputs. They can manipulate their own input however they wish, according to their strategy, and then choose a bit to output. Alice will output a bit <b>a</b> and Bob a bit <b>b</b>\n",
    "\n",
    "\n",
    "Alice and Bob win against the house if the following condition is satisfied:\n",
    "\n",
    "$$ x \\cdot y = a \\oplus b $$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# useful packages \n",
    "import numpy as np\n",
    "import random as rand\n",
    "\n",
    "# importing Qiskit\n",
    "from qiskit import BasicAer\n",
    "from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# You may need to trust this notebook before the button below works"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script>\n",
       "code_show=true; \n",
       "function code_toggle() {\n",
       " if (code_show){\n",
       " $('div.input').hide();\n",
       " } else {\n",
       " $('div.input').show();\n",
       " }\n",
       " code_show = !code_show\n",
       "} \n",
       "$( document ).ready(code_toggle);\n",
       "</script>\n",
       "<form action=\"javascript:code_toggle()\"><input type=\"submit\" value=\"Click here to toggle on/off the raw code.\"></form>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML('''<script>\n",
    "code_show=true; \n",
    "function code_toggle() {\n",
    " if (code_show){\n",
    " $('div.input').hide();\n",
    " } else {\n",
    " $('div.input').show();\n",
    " }\n",
    " code_show = !code_show\n",
    "} \n",
    "$( document ).ready(code_toggle);\n",
    "</script>\n",
    "<form action=\"javascript:code_toggle()\"><input type=\"submit\" value=\"Click here to toggle on/off the raw code.\"></form>''')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Classical strategy\n",
    "\n",
    "Let's first play the game using a deterministic classical strategy. Remember, this means that Alice can only devise a strategy based on her value of the input bit <b>x</b> and Bob according to its input value <b> y </b> and they cannot communicate with each other. Here are a few possible strategies:\n",
    "\n",
    "1) output = input\n",
    "\n",
    "2) output = NOT(input)\n",
    "\n",
    "3) always output = 1 \n",
    "\n",
    "4) always output = 0\n",
    "\n",
    "<b>HINT</b>: the best possible classical strategy for Alice and Bob is to always output the same answer, independently of the input. This gives a 75% winning probability!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cplayer_output(strategy, inp):\n",
    "    if(strategy == 1):\n",
    "        return inp\n",
    "    \n",
    "    elif(strategy == 2):\n",
    "        return abs(inp-1)\n",
    "    \n",
    "    elif(strategy == 3):\n",
    "        return 1\n",
    "        \n",
    "    elif(strategy == 4):\n",
    "        return 0\n",
    "            \n",
    "    else:\n",
    "        print(\"INVALID choice\")\n",
    "        return 100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Let the game begin!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "select the classical strategy for Alice, input 1,2,3 or 4 to pick one of the strategies listed above 1\n",
      "select the classical strategy for Bob, input 1,2,3 or 4 to pick one of the strategies listed above 4\n"
     ]
    }
   ],
   "source": [
    "# Pick Alice's classical strategy\n",
    "A_st = int(input('select the classical strategy for Alice, input 1,2,3 or 4 to pick one of the strategies listed above '))\n",
    "\n",
    "# Pick Bob's classical strategy\n",
    "B_st = int(input('select the classical strategy for Bob, input 1,2,3 or 4 to pick one of the strategies listed above '))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Alice and Bob won the game with probability:  66.0 %\n"
     ]
    }
   ],
   "source": [
    "# fixes the numbers of games to be played\n",
    "N=100\n",
    "\n",
    "# initializes counters used to keep track of the numbers of games won and played by Alice an Bob\n",
    "cont_win = 0 # counts games won\n",
    "cont_tot = 0 # counts games played\n",
    "\n",
    "\n",
    "# play the game N times\n",
    "for i in range(N):\n",
    "    \n",
    "    # generates two random input from the refree, x and y, to be given to Alice and Bob\n",
    "    random_num1 = rand.random() # first random number\n",
    "    random_num2 = rand.random() # second random number\n",
    "\n",
    "    if(random_num1 >= 1/2): # converts the first random number to 0 or 1\n",
    "        x = 0\n",
    "    else: x = 1\n",
    "\n",
    "    if(random_num2 >= 1/2): # converts the second random number to 0 or 1\n",
    "        y = 0\n",
    "    else: y = 1\n",
    "    \n",
    "    \n",
    "    # generates Alice's and Bob's output\n",
    "    a = cplayer_output(A_st, x) # Alice's output\n",
    "    \n",
    "    b = cplayer_output(B_st, y) # Bob's output\n",
    "\n",
    "\n",
    "    # check if the condition for winning the game is met\n",
    "    if(x*y == a^b):\n",
    "        cont_win += 1 # increase thes won games' counter if the condition to win the game is met\n",
    "    \n",
    "    cont_tot += 1 # increases the played games' counter\n",
    "\n",
    "Prob_win = cont_win/cont_tot # winning probability\n",
    "\n",
    "print('Alice and Bob won the game with probability: ', Prob_win*100, '%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Quantum strategy\n",
    "\n",
    "As a quantum strategy, Alice and Bob play the game by sharing an entangled pair of qubit. That is, two qubits are brought together to form an entangled pair and then Alice and Bob are given one each.  Beware, even though the entangled qubits influence each other, it is not possible for Alice and Bob to use them to communicate with each other during the game.\n",
    "\n",
    "According to the input they receive from the refree they will rotate their entangled qubit and then measure it. For example, pick one of the following strategies:\n",
    "\n",
    "1) don't rotate the qubit\n",
    "\n",
    "2) rotate a random amount\n",
    "\n",
    "3) rotate to maximize winning probability\n",
    "\n",
    "\n",
    "<b>HINT</b>: It is possible to prove what is the best angle of rotation for Alice and Bob depending on the input x,y that they receive. This allows for a winning probability of around 85%! Better than any classical strategy! More details can be found in [4]."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def qAlice_output(strategy, inp):\n",
    "    if(strategy == 1):\n",
    "        return 0\n",
    "    \n",
    "    elif(strategy == 2):\n",
    "        return rand.uniform(0,2*np.pi)\n",
    "    \n",
    "    elif(strategy == 3):\n",
    "        if(inp == 0):\n",
    "            return 0\n",
    "        elif(inp == 1):\n",
    "            return np.pi/2        \n",
    "            \n",
    "    else:\n",
    "        print(\"INVALID choice\")\n",
    "        return 100\n",
    "    \n",
    "\n",
    "def qBob_output(strategy, inp):\n",
    "    if(strategy == 1):\n",
    "        return 0\n",
    "    \n",
    "    elif(strategy == 2):\n",
    "        return rand.uniform(0,2*np.pi)\n",
    "    \n",
    "    elif(strategy == 3):\n",
    "        if(inp == 0):\n",
    "            return np.pi/4\n",
    "        elif(inp == 1):\n",
    "            return -np.pi/4        \n",
    "            \n",
    "    else:\n",
    "        print(\"INVALID choice\")\n",
    "        return 100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Let the quantum game begin!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "select the quantum strategy for Alice, input 1,2 or 3 to pick one of the strategies listed above: 3\n",
      "select the quantum strategy for Bob, input 1,2 or 3 to pick one of the strategies listed above: 3\n"
     ]
    }
   ],
   "source": [
    "# Alice's strategy\n",
    "qA_st = int(input('select the quantum strategy for Alice, input 1,2 or 3 to pick one of the strategies listed above: '))\n",
    "\n",
    "# Bob's strategy\n",
    "qB_st = int(input('select the quantum strategy for Bob, input 1,2 or 3 to pick one of the strategies listed above: '))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Alice and Bob won the game with probability:  85.0 %\n"
     ]
    }
   ],
   "source": [
    "# set parameters of the quantum run of the game \n",
    "shots = 1 # set how many times the circuit is run, accumulating statistics about the measurement outcomes \n",
    "backend = BasicAer.get_backend('qasm_simulator') # set the machine where the quantum circuit is to be run   \n",
    "\n",
    "#fixes the numbers of games to be played\n",
    "N=100\n",
    "\n",
    "# initializes counters used to keep track of the numbers of games won and played by Alice an Bob\n",
    "cont_win = 0 # counts games won\n",
    "cont_tot = 0 # counts games played\n",
    "\n",
    "#play N games\n",
    "for i in range(N):\n",
    "\n",
    "    # creates registers for qubits and bits\n",
    "    # creates a quantum register, it specifies the qubits which are going to be used for the program\n",
    "    q = QuantumRegister(2, name='q') \n",
    "    # creates a classical register, the results of the measurement of the qubits are stored here\n",
    "    c = ClassicalRegister(2, name='c') \n",
    "\n",
    "    # creates quantum circuit, to write a quantum algorithm we will add gates to the circuit\n",
    "    game = QuantumCircuit(q, c, name='game')\n",
    "    \n",
    "    # These gates prepare the entangled Bell pair to be shared by Alice and Bob as part of their quantum strategy\n",
    "    # Alice will have qubit 0 and Bob will have qubit 1\n",
    "    game.h(q[0]) # Hadamard gate on qubit 0\n",
    "    game.cx(q[0],q[1]) # CNOT gate on qubit 1 controlled by qubit 0\n",
    "\n",
    "    # generates two random input from the refree, x and y, to be given to Alice and Bob\n",
    "    random_num1 = rand.random() # first random number\n",
    "    random_num2 = rand.random() # second random number\n",
    "\n",
    "    if(random_num1 >= 1/2): # converts the first random number to 0 or 1\n",
    "        x = 0\n",
    "    else: x = 1\n",
    "\n",
    "    if(random_num2 >= 1/2): # converts the second random number to 0 or 1\n",
    "        y = 0\n",
    "    else: y = 1\n",
    "\n",
    "    # The main part of Alice and Bob quantum strategy is to fix different rotation angles for their qubit according to the input x,y\n",
    "    theta = qAlice_output(qA_st, x) # fixes Alice's rotation for her qubit\n",
    "    phi = qBob_output(qB_st, y) # fixes Bob's rotation for his qubit\n",
    "    \n",
    "    # The following gates rotate Alice's qubit and Bob's qubit\n",
    "    game.ry(theta,q[0]) #rotates Alice's qubit of an angle theta\n",
    "    game.ry(phi,q[1]) ##rotates Bob's qubit of an angle phi\n",
    "\n",
    "    # These gates are used to measure  the value of the qubits\n",
    "    game.measure(q[0], c[0]) # measure Alice's qubit and stores the result in a classical bit\n",
    "    game.measure(q[1], c[1]) # measure Bob's qubit and stores the result in a classical bit\n",
    "\n",
    "    # executes circuit and store the output of the measurements\n",
    "    result = execute(game, backend=backend, shots=shots).result()\n",
    "\n",
    "    data = result.get_counts('game') # extract the outcomes and their statistics from the result of the execution\n",
    "    \n",
    "\n",
    "    # reads the result of the measurements of the quantum system\n",
    "    for outcomes in data.keys():\n",
    "        out = outcomes\n",
    "\n",
    "\n",
    "    # converts the result of the measurements contained in the classical register as string '00', '01', '10', '11',\n",
    "    # which are the answers of Alice(a) and Bob (b), from a 'string' type  to 'integer' type \n",
    "    if(out == '00'):\n",
    "        a = 0\n",
    "        b = 0\n",
    "    if(out == '01'):\n",
    "        a = 1\n",
    "        b = 0    \n",
    "    if(out == '10'):\n",
    "        a = 0\n",
    "        b = 1\n",
    "    if(out == '11'):\n",
    "        a = 1\n",
    "        b = 1\n",
    "\n",
    "\n",
    "    # check if the condition for winning the game is met\n",
    "    if(x*y == a^b):\n",
    "        cont_win += 1 # increase thes won games' counter if the condition to win the game is met\n",
    "    \n",
    "    cont_tot += 1 # increases the played games' counter\n",
    "\n",
    "qProb_win = cont_win/cont_tot\n",
    "\n",
    "print('Alice and Bob won the game with probability: ', qProb_win*100, '%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Outcome of the games\n",
    "\n",
    "So, according to the strategies chosen how did you fare?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The quantum strategy gave Alice and Bob higher chances of winning\n"
     ]
    }
   ],
   "source": [
    "if Prob_win > qProb_win :\n",
    "    print(\"The classical strategy gave Alice and Bob higher chances of winning\")\n",
    "else:\n",
    "    print(\"The quantum strategy gave Alice and Bob higher chances of winning\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Best Winning Strategy\n",
    "#### Classical Strategy\n",
    "Let us find the best classical strategy to maximize the winning probability for Alice and Bob. If we consider the following truth table:\n",
    "\n",
    "| x | y | x.y | . | . | . | . | a | b | a$\\oplus$b |\n",
    "|---|---|-----|---|---|---|---|---|---|----|\n",
    "| 0 | 0 | 0   | . | . | . | . | 0 | 0 | 0  |\n",
    "| 0 | 1 | 0   | . | . | . | . | 0 | 1 | 1  |\n",
    "| 1 | 0 | 0   | . | . | . | . | 1 | 0 | 1  |\n",
    "| 1 | 1 | 1   | . | . | . | . | 1 | 1 | 0  |\n",
    "\n",
    "The following table shows the winning conditions:\n",
    "\n",
    "| x | y |    a$\\oplus$b |\n",
    "|---|---|---------------|\n",
    "| 0 | 0 |          a=b  |\n",
    "| 0 | 1 |          a=b  |\n",
    "| 1 | 0 |          a=b  |\n",
    "| 1 | 1 | a=b$\\oplus$1  |\n",
    "\n",
    "Therefore, Alice and Bob can win with probability $3/4$. One possible strategy for Alice and Bob is to ignore the input values and both select \"Always Output=0\" (strategy 4 for Alice and strategy 4 Bob). Another strategy is for Bob to select \"Always Oputput=0\" and Alice gamble by selecting \"Input=Output\" to win if the input $x=1$ and Bob's input $y=0$ (strategy 1 for Alice and strategy 4 Bob). In both strategies, the winning probability is 75%.\n",
    "\n",
    "#### Quantum Strategy\n",
    "Quantum systems offer a degree of freedom with no classical counterpart. If before the game starts Alice and Bob share an entangled bipartite state, they can win with a probability of $cos^{2}(\\frac{\\pi}{8})\\approx  85\\%$. The winning strategy is as follows [4]:\n",
    "\n",
    "1- Alice and Bob share two-qubit EPR (Einstein–Podolsky–Rosen) state:\n",
    "$$ |\\Psi\\rangle_{AB}=\\frac{1}{\\sqrt{2}}(|0\\rangle_{A}\\otimes|0\\rangle_{B}+|1\\rangle_{A}\\otimes|1\\rangle_{B}) $$\n",
    "Where state $A$ belongs to Alice and State $B$ belongs to Bob.\n",
    "\n",
    "2- They define a measurement bases denoted by $v_{i}(\\theta)$ where $\\theta \\in [0,2\\pi)$:\n",
    "\n",
    "$$\n",
    "|v_{0}(\\theta)\\rangle = cos(\\theta)|0\\rangle + sin (\\theta)|1\\rangle\n",
    "$$\n",
    "$$\n",
    "|v_{1}(\\theta)\\rangle = -sin(\\theta)|0\\rangle + cos (\\theta)|1\\rangle\n",
    "$$\n",
    "\n",
    "Based on the input value Alice and Bob a measurement bases. The following are all possible winning probability after substituting $ v_{i}(\\theta)  $ and $ |\\Psi\\rangle_{AB}$\n",
    "\n",
    "###### Alice $x=0$, Bob $y=0$\n",
    "\n",
    "$$\n",
    "P_{0,0} = |\\langle _{AV0}(\\theta_{A0}) \\otimes \\langle _{BV0}(\\theta_{B0}) \\otimes  |\\Psi\\rangle_{AB}|^2 + |\\langle _{AV1}(\\theta_{A0}) \\otimes \\langle _{BV1}(\\theta_{B0}) \\otimes  |\\Psi\\rangle_{AB}|^2\n",
    "$$\n",
    "$$ P_{0,0} = cos^{2}(\\theta_{A0} - \\theta_{B0}) $$\n",
    "\n",
    "###### Alice $x=0$, Bob $y=1$\n",
    "\n",
    "$$\n",
    "P_{0,1} = |\\langle _{AV0}(\\theta_{A0}) \\otimes \\langle _{BV0}(\\theta_{B1}) \\otimes  |\\Psi\\rangle_{AB}|^2 + |\\langle _{AV1}(\\theta_{A0}) \\otimes \\langle _{BV1}(\\theta_{B1}) \\otimes  |\\Psi\\rangle_{AB}|^2\n",
    "$$\n",
    "$$ P_{0,1} = cos^{2}(\\theta_{A0} - \\theta_{B1}) $$\n",
    "\n",
    "###### Alice $x=1$, Bob $y=0$\n",
    "\n",
    "$$\n",
    "P_{1,0} = |\\langle _{AV0}(\\theta_{A1}) \\otimes \\langle _{BV0}(\\theta_{B0}) \\otimes  |\\Psi\\rangle_{AB}|^2 + |\\langle _{AV1}(\\theta_{A1}) \\otimes \\langle _{BV1}(\\theta_{B0}) \\otimes  |\\Psi\\rangle_{AB}|^2\n",
    "$$\n",
    "$$ P_{1,0} = cos^{2}(\\theta_{A1} - \\theta_{B0}) $$\n",
    "\n",
    "###### Alice $x=1$ , Bob $y=1$\n",
    "\n",
    "$$\n",
    "P_{1,1} = |\\langle _{AV0}(\\theta_{A1}) \\otimes \\langle _{BV1}(\\theta_{B1}) \\otimes  |\\Psi\\rangle_{AB}|^2 + |\\langle _{AV1}(\\theta_{A1}) \\otimes \\langle _{BV0}(\\theta_{B1}) \\otimes  |\\Psi\\rangle_{AB}|^2\n",
    "$$\n",
    "$$ P_{1,1} = sin^{2}(\\theta_{A1} - \\theta_{B1}) $$\n",
    "\n",
    "Alice and Bob choose a set of angles separated by $22.5^\\circ$ To maximize their winning probability. For example, Alice chooses $ \\{ \\theta_{A0}=0, \\theta_{A1}=\\frac{\\pi}{4} \\}$ and Bob chooses $ \\{  \\theta_{B0}=\\frac{\\pi}{8}, \\theta_{B1}=-\\frac{\\pi}{8} \\}$ . The overall winning probability using the quantum system is:\n",
    "$$\n",
    "P_{0,0} + P_{0,1} + P_{1,0}+P_{1,1}\n",
    "$$\n",
    "\n",
    "$$\n",
    "cos^{2}(\\frac{\\pi}{8}) + cos^{2}(\\frac{\\pi}{8})+cos^{2}(\\frac{\\pi}{8})+sin^{2}(\\frac{3\\pi}{8})\n",
    "$$\n",
    "\n",
    "$$\n",
    "\\frac{3}{4} cos^{2}(\\frac{\\pi}{8}) + \\frac{1}{4} sin^{2}(\\frac{3\\pi}{8}) \\approx 85\\%\n",
    "$$\n",
    "\n",
    "If Alice and Bob choose \"rotate to maximize winning probability\" (strategy 3 for Alice and strategy 3 Bob) they get a higher probability of winning using the quantum system than the classical system $ 85\\% > 75\\%$ ."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "\n",
    "# References\n",
    "\n",
    "[1] M. A. Nielsen and I. L. Chuang, Quantum Computation and Quantum Information (Cambridge University Press, 2000).\n",
    "\n",
    "[2] J. S. Bell, Speakable and unspeakable in quantum mechanics: Collected papers on quantum philosophy (Cambridge university press, 2004).\n",
    "\n",
    "[3] J. F. Clauser, M. A. Horne, A. Shimony, and R. A. Holt, Proposed experiment to test local hidden-variable theories, Physical review letters, 23 (1969), p. 880.\n",
    "\n",
    "[4] Detailed description of optimal quantum strategy:\n",
    "\n",
    "https://sergworks.wordpress.com/2016/10/26/chsh-game-in-detail/\n",
    "\n",
    "[5] connection between CHSH game and Bell's inequalities:\n",
    "\n",
    "https://cs.uwaterloo.ca/~watrous/CPSC519/LectureNotes/20.\n",
    "\n",
    "https://www-m5.ma.tum.de/foswiki/pub/M5/Allgemeines/OS_QIT_2016S/Vortrag7.pdf\n",
    "\n",
    "\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
